package com.zzedu.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
import com.google.common.collect.Lists;
import com.zzedu.common.enums.CommonEnums;
import com.zzedu.domain.*;
import com.zzedu.mapper.ZzCourseMapper;
import com.zzedu.service.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 *
 */
@Component
public class InitDataServiceImpl {

    @Autowired
    IZzSchoolService zzSchoolService;

    @Autowired
    IZzSchoolCourseService zzSchoolCourseService;
    @Autowired
    ZzCourseMapper zzCourseMapper;

    @Autowired
    IZzCourseService zzCourseService;

    @Autowired
    IZzClassesSendStudentService zzClassesSendStudentService;

    @Autowired
    IZzClassesService zzClassesService;

    @Autowired
    IZzStudentExtendService zzStudentExtendService;

    @Autowired
    IZzExerciseBookService zzExerciseBookService;

    @Autowired
    IZzPictureBookService zzPictureBookService;

    //    @PostConstruct
    public void init() {
//        initSchoolUnLock();
//        stepUnlockUnitTwo();
//        nextSchoolLock();
//        unLockStudent();
    }

    /**
     * 解锁创建时候初始化课程
     */
    public void initSchoolUnLock() {
        LambdaQueryWrapper<ZzSchool> queryWrapper = Wrappers.lambdaQuery(ZzSchool.class);
        List<ZzSchool> zzSchoolList = zzSchoolService.list(queryWrapper);
        for (ZzSchool zzSchool : zzSchoolList) {
            // 生成初始化解锁 学校unit 解锁课表
            List<String> levelList = JSON.parseArray(zzSchool.getLevel(), String.class);
            Integer unLimitCount = 2;
            if (null != zzSchool.getBookCount()) {
                unLimitCount = zzSchool.getBookCount();
            }
            for (String level : levelList) {
                // 按照级别 按照unit 序号 获取初始化unit
                List<ZzCourse> zzCourseList = zzCourseMapper.selectList(Wrappers.lambdaQuery(ZzCourse.class)
                        .eq(ZzCourse::getLevel, level)
                        .eq(ZzCourse::getState, CommonEnums.YES.getCode())
                        .orderByAsc(ZzCourse::getSortNo)
                        .orderByAsc(ZzCourse::getId)
                        .last("limit " + unLimitCount)
                );
                if (CollectionUtils.isNotEmpty(zzCourseList)) {
                    for (ZzCourse course : zzCourseList) {
                        ZzSchoolCourse zzSchoolCourse = new ZzSchoolCourse();
                        zzSchoolCourse.setLevel(level);
                        zzSchoolCourse.setUnitId(course.getId());
                        zzSchoolCourse.setUnLockDate(LocalDateTime.now());
                        zzSchoolCourse.setSchoolId(zzSchool.getId());
                        zzSchoolCourseService.save(zzSchoolCourse);
                    }
                }
            }
        }
    }

    /**
     * 根据学习记录补充需要解锁的unit_id
     */
    public void stepUnlockUnitTwo() {
        String sql = " select DISTINCT b.school_id,c.unit_id,d.sort_no,d.`level` from zz_exercise_book a" +
                "        left join zz_student b on b.id=a.student_id" +
                "        left join zz_picture_book c on c.id=a.picture_book_id" +
                "        left join zz_course d on d.id=c.unit_id" +
                "        order by d.`level`,d.sort_no";

        List<Map<String, Object>> list = SqlRunner.db().selectList(sql);
        if (CollectionUtils.isNotEmpty(list)) {
            for (Map map : list) {
                Long schoolId = MapUtils.getLong(map, "school_id");
                Long unitId = MapUtils.getLong(map, "unit_id");
                String level = MapUtils.getString(map, "level");
                try {
                    ZzSchoolCourse zzSchoolCourse = new ZzSchoolCourse();
                    zzSchoolCourse.setLevel(level);
                    zzSchoolCourse.setUnitId(unitId);
                    zzSchoolCourse.setUnLockDate(LocalDateTime.now());
                    zzSchoolCourse.setSchoolId(schoolId);
                    zzSchoolCourseService.save(zzSchoolCourse);
                } catch (Exception e) {
                }
            }
        }
    }

    /**
     * 查询当前学校解锁级别
     */
    public void nextSchoolLock() {
        //10.1号 之前 小于 4 需要额外开放的校区名单
        String sql = "select school_id,`level`,count(*) num from zz_school_course GROUP BY school_id,`level` HAVING COUNT(*)<4";
        List<Map<String, Object>> list = SqlRunner.db().selectList(sql);
        if (CollectionUtils.isNotEmpty(list)) {
            for (Map map : list) {
                Long schoolId = MapUtils.getLong(map, "school_id");
                Long num = MapUtils.getLong(map, "num");
                String level = MapUtils.getString(map, "level");
                //获取解锁
                ZzCourse unLockZzCourse = zzCourseService.getOne(Wrappers.lambdaQuery(ZzCourse.class)
                        .eq(ZzCourse::getLevel, level)
                        .eq(ZzCourse::getState, CommonEnums.YES.getCode())
                        .notExists("select unit_id from zz_school_course where deleted=0 and school_id={0} and level={1} and unit_id=zz_course.id", schoolId, level)
                        .orderByAsc(ZzCourse::getSortNo)
                        .orderByAsc(ZzCourse::getId)
                        .last("limit 1")
                );
                if (null != unLockZzCourse) {
                    ZzSchoolCourse zzSchoolCourse = new ZzSchoolCourse();
                    zzSchoolCourse.setLevel(level);
                    zzSchoolCourse.setUnitId(unLockZzCourse.getId());
                    zzSchoolCourse.setUnLockDate(LocalDateTime.now());
                    zzSchoolCourse.setSchoolId(schoolId);
                    if (null == zzSchoolCourseService.getOne(Wrappers.lambdaQuery(ZzSchoolCourse.class)
                            .eq(ZzSchoolCourse::getSchoolId, schoolId)
                            .eq(ZzSchoolCourse::getUnLockDate, unLockZzCourse.getId())
                            .last("limit 1 ")
                    )) {
                        zzSchoolCourseService.save(zzSchoolCourse);
                    }
                }
            }
        }
    }

    /**
     * 解锁学生绘本
     */

    public void unLockStudent() {
        //学生学习记录
        String sql = "INSERT into zz_classes_send_student(" +
                "stu_id,book_id,unit_id,school_id,deleted,un_lock_date,gmt_create,bus_date " +
                ")" +
                "SELECT " +
                "DISTINCT " +
                "\ta.student_id," +
                "\ta.picture_book_id," +
                "\tb.unit_id," +
                "\tc.id," +
                "\t0," +
                "\tnow()," +
                "\tnow()," +
                "\tDATE_FORMAT(NOW(),'%Y-%m-%d')" +
                " FROM " +
                "\tzz_exercise_book a" +
                "\tLEFT JOIN zz_picture_book b ON a.picture_book_id = b.id " +
                "\tLEFT join zz_student d on d.id=a.student_id " +
                "\tleft join zz_school c on c.id=d.school_id " +
                "\twhere a.deleted=0" +
                "\tand a.student_id in(select id from zz_student where deleted=0)";
        SqlRunner.db().insert(sql);
        //根据学习记录查找对应的班级和老师
        List<ZzClassesSendStudent> zzClassesSendStudents = this.zzClassesSendStudentService.list();
        for (ZzClassesSendStudent zzClassesSendStudent : zzClassesSendStudents) {
            CompletableFuture.runAsync(() -> {
                ZzExerciseBook zzExerciseBook = this.zzExerciseBookService.getOne(Wrappers.lambdaQuery(ZzExerciseBook.class)
                        .eq(ZzExerciseBook::getPictureBookId, zzClassesSendStudent.getBookId())
                        .eq(ZzExerciseBook::getStudentId, zzClassesSendStudent.getStuId())
                        .isNotNull(ZzExerciseBook::getClazzId)
                        .last("limit 1 ")
                );
                if (null != zzExerciseBook) {
                    zzClassesSendStudent.setClzzId(zzExerciseBook.getClazzId());
                    ZzClasses zzClasses = zzClassesService.getBaseMapper().selectById(zzClassesSendStudent.getClzzId());
                    if (null != zzClasses) {
                        zzClassesSendStudent.setTeacherId(zzClasses.getTeacherId());
                        zzClassesSendStudentService.updateById(zzClassesSendStudent);
                    }
                }
            });
        }
    }

    /**
     * 补充遗漏绘本
     */
//    @PostConstruct
    public void extendSendBook() {
        String sql = "select a.stu_id,a.unit_id,b.sort_no,count(*) from zz_classes_send_student a \n" +
                "left join zz_course b on b.id=a.unit_id\n" +
                "GROUP BY a.stu_id,a.unit_id,b.sort_no HAVING count(*)<8 ";
        List<Map<String, Object>> list = SqlRunner.db().selectList(sql);
        int len = list.size();
        int index = 0;
        for (int i = 0; i < len; i++) {
            Map map = list.get(i);
            index++;
            final Long stuId = MapUtils.getLong(map, "stu_id");
            final Long unitId = MapUtils.getLong(map, "unit_id");
            if (index < len - 1) {
                Long nextStuId = MapUtils.getLong(list.get(index), "stu_id");
                if (stuId != nextStuId && !stuId.equals(nextStuId)) {
                    continue;
                }
            } else {
                continue;
            }
            CompletableFuture.runAsync(() -> {
                ZzClassesSendStudent zzClassesSendStudent = this.zzClassesSendStudentService.getOne(Wrappers.lambdaQuery(ZzClassesSendStudent.class)
                        .eq(ZzClassesSendStudent::getStuId, stuId)
                        .eq(ZzClassesSendStudent::getUnitId, unitId)
                        .orderByDesc(ZzClassesSendStudent::getId)
                        .last("limit 1")
                );
                zzClassesSendStudent.setId(null);
                List<ZzPictureBook> zzPictureBookList = this.zzPictureBookService.list(
                        Wrappers.lambdaQuery(ZzPictureBook.class)
                                .eq(ZzPictureBook::getUnitId, unitId)
                                .in(ZzPictureBook::getShowModel, Lists.newArrayList(1, 3))
                                .orderByAsc(ZzPictureBook::getSortNo)
                );
                for (ZzPictureBook zzPictureBook : zzPictureBookList) {
                    zzClassesSendStudent.setUnitId(unitId);
                    zzClassesSendStudent.setBookId(zzPictureBook.getId());
                    zzClassesSendStudent.setUnLockDate(LocalDateTime.now());
                    zzClassesSendStudent.setBusDate("09-13");
                    zzClassesSendStudent.setStuId(stuId);
                    try {
                        this.zzClassesSendStudentService.save(zzClassesSendStudent);
                        zzClassesSendStudent.setId(null);
                    } catch (Exception e) {
                    }
                }
            });
        }
    }

    /**
     * 多开2个绘本
     */
//    @PostConstruct
    public void decrHourCount() {
        String sql = "select a.stu_id,a.unit_id,b.sort_no,count(*) num from zz_classes_send_student a \n" +
                "left join zz_course b on b.id=a.unit_id\n" +
                "GROUP BY a.stu_id,a.unit_id,b.sort_no  HAVING count(*)<8";
        List<Map<String, Object>> list = SqlRunner.db().selectList(sql);
        int len = list.size();
        for (Map map : list) {
            CompletableFuture.runAsync(() -> {
                final Long stuId = MapUtils.getLong(map, "stu_id");
                final Long unitId = MapUtils.getLong(map, "unit_id");
                final Integer count = MapUtils.getInteger(map, "num");
                List<ZzPictureBook> zzPictureBookList = Lists.newArrayList();
                if (count < 7) {
                    String bookSQL = "select max(b.sort_no) sortNo from zz_classes_send_student a inner join zz_picture_book b on b.id=a.book_id\n" +
                            "where a.stu_id=" + stuId + " and a.unit_id= " + unitId;

                    List<ZzPictureBook> allZzPictureBookList = this.zzPictureBookService.list(Wrappers.lambdaQuery(ZzPictureBook.class).eq(ZzPictureBook::getUnitId, unitId)
                            .in(ZzPictureBook::getShowModel, Lists.newArrayList(1, 3))
                            .apply("sort_no>(" + bookSQL + ")")
                            .orderByAsc(ZzPictureBook::getSortNo).last("limit 2")
                    );
                    zzPictureBookList.addAll(allZzPictureBookList);
                } else {
                    //count =7 or 8
                    String bookSQL = "select max(b.sort_no) sortNo from zz_classes_send_student a inner join zz_picture_book b on b.id=a.book_id\n" +
                            "where a.stu_id=" + stuId + " and a.unit_id= " + unitId;

                    List<ZzPictureBook> allZzPictureBookList = this.zzPictureBookService.list(Wrappers.lambdaQuery(ZzPictureBook.class).eq(ZzPictureBook::getUnitId, unitId)
                            .in(ZzPictureBook::getShowModel, Lists.newArrayList(1, 3))
                            .apply("sort_no>(" + bookSQL + ")")
                            .orderByAsc(ZzPictureBook::getSortNo).last("limit 2")
                    );
                    if (CollectionUtils.isNotEmpty(allZzPictureBookList)) {
                        zzPictureBookList.addAll(allZzPictureBookList);
                    }
                    //获取unit 下一级
                    ZzCourse zzCourse = this.zzCourseService.getById(unitId);
                    ZzCourse nextZzCourse = this.zzCourseService.getOne(Wrappers.lambdaQuery(ZzCourse.class)
                            .eq(ZzCourse::getLevel, zzCourse.getLevel())
                            .gt(ZzCourse::getSortNo, zzCourse.getSortNo())
                            .eq(ZzCourse::getState, CommonEnums.YES.getCode())
                            .orderByAsc(ZzCourse::getSortNo).last("limit 1")
                    );
                    if (!CollectionUtils.isNotEmpty(allZzPictureBookList)) {
                        allZzPictureBookList = this.zzPictureBookService.list(Wrappers.lambdaQuery(ZzPictureBook.class).eq(ZzPictureBook::getUnitId, nextZzCourse.getId())
                                .in(ZzPictureBook::getShowModel, Lists.newArrayList(1, 3))
                                .eq(ZzPictureBook::getState, CommonEnums.YES.getCode())
                                .orderByAsc(ZzPictureBook::getSortNo).last("limit 2")
                        );
                        zzPictureBookList.addAll(allZzPictureBookList);
                    } else {
                        allZzPictureBookList = this.zzPictureBookService.list(Wrappers.lambdaQuery(ZzPictureBook.class).eq(ZzPictureBook::getUnitId, nextZzCourse.getId())
                                .in(ZzPictureBook::getShowModel, Lists.newArrayList(1, 3))
                                .orderByAsc(ZzPictureBook::getSortNo).last("limit 1")
                        );
                        zzPictureBookList.addAll(allZzPictureBookList);
                    }
                }
                ZzClassesSendStudent zzClassesSendStudent = this.zzClassesSendStudentService.getOne(Wrappers.lambdaQuery(ZzClassesSendStudent.class)
                        .eq(ZzClassesSendStudent::getStuId, stuId)
                        .eq(ZzClassesSendStudent::getUnitId, unitId)
                        .orderByDesc(ZzClassesSendStudent::getId)
                        .last("limit 1")
                );
                for (ZzPictureBook zzPictureBook : zzPictureBookList) {
                    zzClassesSendStudent.setId(null);
                    zzClassesSendStudent.setUnitId(zzPictureBook.getUnitId());
                    zzClassesSendStudent.setBookId(zzPictureBook.getId());
                    zzClassesSendStudent.setUnLockDate(LocalDateTime.now());
                    zzClassesSendStudent.setBusDate("09-15");
                    zzClassesSendStudent.setStuId(stuId);
                    try {
                        this.zzClassesSendStudentService.save(zzClassesSendStudent);
                        zzClassesSendStudent.setId(null);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
}
